#include "stdafx.h"

CSocketIcmp::CSocketIcmp()
{
	id = seq = 0;
	ttl = 0;
	ip = 0;
	time_send = 0;
	time_recv = 0;
	CSocketIcmpPool::getInstance().get_idseq(id, seq);
	uint32_t handle = (id << 16) & 0xFFFF0000;
	handle |= seq;
	hHanlde = CSocketIcmpPool::getInstance().regClass(this,handle);
}


CSocketIcmp::~CSocketIcmp()
{
	CSocketIcmpPool::getInstance().unregClass(hHanlde);
}

void CSocketIcmp::get_reply(uint8_t &xttl, uint32_t &xtime)
{
	xttl = 0;
	xtime = uint32_t(-1);
	if (xxEvent.Wait())
	{
		xtime = time_recv - time_send;
		xtime /= 10;//us
		xtime /= 1000;//ms
		xttl = ttl;
		xxEvent.Reset();
	}
}

void CSocketIcmp::ProcessRx(uint8_t _ttl, uint32_t _time, uint32_t src_ip)
{
	ttl = _ttl;
	time_recv = _time;
	ip = src_ip;
	xxEvent.Set();
}

void CSocketIcmp::ping_ip(uint32_t xip)
{
	uint8_t packet_pad[sizeof(icmp_header)+32] = {};
	RtlZeroMemory(packet_pad, sizeof(packet_pad));
	auto icmphdr = reinterpret_cast<icmp_header*>(packet_pad);
	icmphdr->Type = 8;
	icmphdr->id = id;
	icmphdr->sqe = seq;
	for (auto i = 8; i < 40; i++)
		packet_pad[i] = 'A';
	auto localip = *(uint32_t*)Ipv4.getLocalIp();
	auto sum = icmp_checksum(icmphdr, 40);
	icmphdr->checksum = sum;
	Ipv4.TxPacket(xip, localip, IP_PROTO_ICMP, packet_pad, sizeof(packet_pad));
	time_send = (uint32_t)getTime();

}